home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir27 / calctool.zip / MATHLIB.C < prev    next >
C/C++ Source or Header  |  1994-01-12  |  70KB  |  2,440 lines

  1.  
  2. /*  @(#)mathlib.c 1.4 90/03/26
  3.  *
  4.  *  These are the mathematical routines used by calctool.
  5.  *
  6.  *  This is being done because libm.a doesn't appear to be as portable
  7.  *  as originally assumed.
  8.  *
  9.  *  It is hoped that your system supplies all the mathematical functions
  10.  *  required by calctool. If not then, it is possible to use the needed
  11.  *  ones from this library. Look in mathlib.h for a set of definitions,
  12.  *  and uncomment and set appropriately.
  13.  *
  14.  *  These routines are taken from two sources:
  15.  *
  16.  *  1/ Fred Fishs' portable maths library which was posted to the
  17.  *     comp.sources.unix newsgroup on April 1987.
  18.  *
  19.  *     acos, acosh, asin, asinh, atan, atanh, cos, cosh, dabs,
  20.  *     exp, log, log10, mod, poly, sin, sinh, sqrt, tan, tanh.
  21.  *
  22.  *  2/ The BSD4.3 maths library found on uunet in
  23.  *     bsd_sources/src/usr.lib/libm.
  24.  *
  25.  *     pow, pow_p, scalb, logb, copysign, finite, drem, exp__E,
  26.  *     log__L.
  27.  *
  28.  *  Customised and condensed by Rich Burridge,
  29.  *                              Sun Microsystems, Australia.
  30.  *
  31.  *  Permission is given to distribute these sources, as long as the
  32.  *  copyright messages are not removed, and no monies are exchanged.
  33.  *
  34.  *  No responsibility is taken for any errors or inaccuracies inherent
  35.  *  either to the comments or the code of this program, but if
  36.  *  reported to me then an attempt will be made to fix them.
  37.  */
  38.  
  39. /************************************************************************
  40.  *                                                                      *
  41.  *                              N O T I C E                             *
  42.  *                                                                      *
  43.  *                      Copyright Abandoned, 1987, Fred Fish            *
  44.  *                                                                      *
  45.  *      This previously copyrighted work has been placed into the       *
  46.  *      public domain by the author (Fred Fish) and may be freely used  *
  47.  *      for any purpose, private or commercial.  I would appreciate     *
  48.  *      it, as a courtesy, if this notice is left in all copies and     *
  49.  *      derivative works.  Thank you, and enjoy...                      *
  50.  *                                                                      *
  51.  *      The author makes no warranty of any kind with respect to this   *
  52.  *      product and explicitly disclaims any implied warranties of      *
  53.  *      merchantability or fitness for any particular purpose.          *
  54.  *                                                                      *
  55.  ************************************************************************
  56.  */
  57.  
  58. #include <stdio.h>
  59. #include <errno.h>
  60. #include "mathlib.h"
  61. #include "calctool.h"
  62.  
  63. double atan(), cos(), cosh(), dabs(), exp(), frexp() ;
  64. double ldexp(), log(), mod(), modf(), poly(), sin() ;
  65. double sinh(), sqrt() ;
  66.  
  67. extern double frexp(), ldexp(), modf() ;
  68.  
  69.  
  70. /*  FUNCTION
  71.  *
  72.  *      acos   double precision arc cosine
  73.  *
  74.  *  DESCRIPTION
  75.  *
  76.  *      Returns double precision arc cosine of double precision
  77.  *      floating point argument.
  78.  *
  79.  *  USAGE
  80.  *
  81.  *      double acos(x)
  82.  *      double x ;
  83.  *
  84.  *  REFERENCES
  85.  *
  86.  *      Fortran IV-plus user's guide, Digital Equipment Corp. pp B-1.
  87.  *
  88.  *  RESTRICTIONS
  89.  *
  90.  *      The maximum relative error for the approximating polynomial
  91.  *      in atan is 10**(-16.82).  However, this assumes exact arithmetic
  92.  *      in the polynomial evaluation.  Additional rounding and
  93.  *      truncation errors may occur as the argument is reduced
  94.  *      to the range over which the polynomial approximation
  95.  *      is valid, and as the polynomial is evaluated using
  96.  *      finite-precision arithmetic.
  97.  *
  98.  *  INTERNALS
  99.  *
  100.  *      Computes arccosine(x) from:
  101.  *
  102.  *              (1)     If x < -1.0  or x > +1.0 then call
  103.  *                      doerr and return 0.0 by default.
  104.  *
  105.  *              (2)     If x = 0.0 then acos(x) = PI/2.
  106.  *
  107.  *              (3)     If x = 1.0 then acos(x) = 0.0
  108.  *
  109.  *              (4)     If x = -1.0 then acos(x) = PI.
  110.  *
  111.  *              (5)     If 0.0 < x < 1.0 then
  112.  *                      acos(x) = atan(Y)
  113.  *                      Y = sqrt[1-(x**2)] / x
  114.  *
  115.  *              (6)     If -1.0 < x < 0.0 then
  116.  *                      acos(x) = atan(Y) + PI
  117.  *                      Y = sqrt[1-(x**2)] / x
  118.  */
  119.  
  120. #ifdef   NEED_ACOS
  121. double
  122. acos(x)
  123. double x ;
  124. {
  125.   double y ;
  126.   auto double retval ;
  127.  
  128.   if (x > 1.0 || x < -1.0)
  129.     {
  130.       doerr("acos", "DOMAIN", EDOM) ;
  131.       retval = 0.0 ;
  132.     }
  133.   else if (x == 0.0)  retval = HALFPI ;
  134.   else if (x == 1.0)  retval = 0.0 ;
  135.   else if (x == -1.0) retval = PI ;
  136.   else
  137.     {
  138.       y = atan(sqrt(1.0 - (x * x)) / x) ;
  139.       if (x > 0.0) retval = y ;
  140.       else retval = y + PI ;
  141.     }    
  142.   return(retval) ;
  143. }
  144. #endif /*NEED_ACOS*/
  145.  
  146.  
  147. /*  FUNCTION
  148.  *
  149.  *      acosh   double precision hyperbolic arc cosine
  150.  *
  151.  *  DESCRIPTION
  152.  *
  153.  *      Returns double precision hyperbolic arc cosine of double precision
  154.  *      floating point number.
  155.  *
  156.  *  USAGE
  157.  *
  158.  *      double acosh(x)
  159.  *      double x ;
  160.  *
  161.  *  RESTRICTIONS
  162.  *
  163.  *      The range of the ACOSH function is all real numbers greater
  164.  *      than or equal to 1.0 however large arguments may cause
  165.  *      overflow in the x squared portion of the function evaluation.
  166.  *
  167.  *      For precision information refer to documentation of the
  168.  *      floating point library primatives called.
  169.  *
  170.  *  INTERNALS
  171.  *
  172.  *      Computes acosh(x) from:
  173.  *
  174.  *              1.      If x < 1.0 then report illegal
  175.  *                      argument and return zero.
  176.  *
  177.  *              2.      If x > sqrt(MAXDOUBLE) then
  178.  *                      set x = sqrt(MAXDOUBLE and
  179.  *                      continue after reporting overflow.
  180.  *
  181.  *              3.      acosh(x) = log [x+sqrt(x**2 - 1)]
  182.  */
  183.  
  184. #ifdef   NEED_ACOSH
  185. double
  186. acosh(x)
  187. double x ;
  188. {
  189.   auto double retval ;
  190.  
  191.   if (x < 1.0)
  192.     {
  193.       doerr("acosh", "DOMAIN", ERANGE) ;
  194.       retval = 0.0 ;
  195.     }
  196.   else if (x > SQRT_MAXDOUBLE)
  197.     {
  198.       doerr("acosh", "OVERFLOW", ERANGE) ;
  199.       x = SQRT_MAXDOUBLE ;
  200.       retval = log(2* SQRT_MAXDOUBLE) ;
  201.     }
  202.   else retval = log(x + sqrt(x*x - 1.0)) ;
  203.   return(retval) ;
  204. }
  205. #endif /*NEED_ACOSH*/
  206.  
  207.  
  208. /*
  209.  *  FUNCTION
  210.  *
  211.  *      asin   double precision arc sine
  212.  *
  213.  *  DESCRIPTION
  214.  *
  215.  *      Returns double precision arc sine of double precision
  216.  *      floating point argument.
  217.  *
  218.  *      If argument is less than -1.0 or greater than +1.0, calls
  219.  *      doerr with a DOMAIN error.  If doerr does not handle
  220.  *      the error then prints error message and returns 0.
  221.  *
  222.  *  USAGE
  223.  *
  224.  *      double asin(x)
  225.  *      double x ;
  226.  *
  227.  *  REFERENCES
  228.  *
  229.  *      Fortran IV-plus user's guide, Digital Equipment Corp. pp B-2.
  230.  *
  231.  *  RESTRICTIONS
  232.  *
  233.  *      For precision information refer to documentation of the floating
  234.  *      point library primatives called.
  235.  *
  236.  *  INTERNALS
  237.  *
  238.  *      Computes arcsine(x) from:
  239.  *
  240.  *              (1)     If x < -1.0 or x > +1.0 then
  241.  *                      call doerr and return 0.0 by default.
  242.  *
  243.  *              (2)     If x = 0.0 then asin(x) = 0.0
  244.  *
  245.  *              (3)     If x = 1.0 then asin(x) = PI/2.
  246.  *
  247.  *              (4)     If x = -1.0 then asin(x) = -PI/2
  248.  *
  249.  *              (5)     If -1.0 < x < 1.0 then
  250.  *                      asin(x) = atan(y)
  251.  *                      y = x / sqrt[1-(x**2)]
  252.  */
  253.  
  254. #ifdef NEED_ASIN
  255. double
  256. asin(x)
  257. double x ;
  258. {
  259.   auto double retval ;
  260.  
  261.   if ( x > 1.0 || x < -1.0)
  262.     {
  263.       doerr("asin", "DOMAIN", EDOM) ;
  264.       retval = 0.0 ;
  265.     }
  266.   else if (x == 0.0) retval = 0.0 ;
  267.   else if (x == 1.0) retval = HALFPI ;
  268.   else if (x == -1.0) retval = -HALFPI ;
  269.   else retval = atan(x / sqrt (1.0 - (x * x))) ;
  270.   return(retval) ;
  271. }
  272. #endif /*NEED_ASIN*/
  273.  
  274.  
  275. /*  FUNCTION
  276.  *
  277.  *      asinh   double precision hyperbolic arc sine
  278.  *
  279.  *  DESCRIPTION
  280.  *
  281.  *      Returns double precision hyperbolic arc sine of double precision
  282.  *      floating point number.
  283.  *
  284.  *  USAGE
  285.  *
  286.  *      double asinh(x)
  287.  *      double x ;
  288.  *
  289.  *  RESTRICTIONS
  290.  *
  291.  *      The domain of the ASINH function is the entire real axis
  292.  *      however the evaluation of x squared may cause overflow
  293.  *      for large magnitudes.
  294.  *
  295.  *      For precision information refer to documentation of the
  296.  *      floating point library routines called.
  297.  *
  298.  *  INTERNALS
  299.  *
  300.  *      Computes asinh(x) from:
  301.  *
  302.  *              1.      Let xmax = sqrt(MAXDOUBLE - 1)
  303.  *
  304.  *              2.      If x < -xmax or xmax < x then
  305.  *                      let x = xmax and flag overflow.
  306.  *
  307.  *              3.      asinh(x) = log [x+sqrt(x**2 + 1)]
  308.  */
  309.  
  310. #ifdef NEED_ASINH
  311. double
  312. asinh(x)
  313. double x ;
  314. {
  315.   auto double retval ;
  316.  
  317.   if (x < -SQRT_MAXDOUBLE || x > SQRT_MAXDOUBLE)
  318.     {
  319.       doerr("asinh", "OVERFLOW", ERANGE) ;
  320.       retval = log(2 * SQRT_MAXDOUBLE) ;
  321.     }
  322.   else retval = log(x + sqrt(x*x + 1.0)) ;
  323.   return(retval) ;
  324. }
  325. #endif /*NEED_ASINH*/
  326.  
  327.  
  328. /*  FUNCTION
  329.  *
  330.  *      atan   double precision arc tangent
  331.  *
  332.  *  DESCRIPTION
  333.  *
  334.  *      Returns double precision arc tangent of double precision
  335.  *      floating point argument.
  336.  *
  337.  *  USAGE
  338.  *
  339.  *      double atan(x)
  340.  *      double x ;
  341.  *
  342.  *  REFERENCES
  343.  *
  344.  *      Fortran 77 user's guide, Digital Equipment Corp. pp B-3
  345.  *
  346.  *      Computer Approximations, J.F. Hart et al, John Wiley & Sons,
  347.  *      1968, pp. 120-130.
  348.  *
  349.  *  RESTRICTIONS
  350.  *
  351.  *      The maximum relative error for the approximating polynomial
  352.  *      is 10**(-16.82).  However, this assumes exact arithmetic
  353.  *      in the polynomial evaluation.  Additional rounding and
  354.  *      truncation errors may occur as the argument is reduced
  355.  *      to the range over which the polynomial approximation
  356.  *      is valid, and as the polynomial is evaluated using
  357.  *      finite-precision arithmetic.
  358.  *
  359.  *  INTERNALS
  360.  *
  361.  *      Computes arctangent(x) from:
  362.  *
  363.  *              (1)     If x < 0 then negate x, perform steps
  364.  *                      2, 3, and 4, and negate the returned
  365.  *                      result.  This makes use of the identity
  366.  *                      atan(-x) = -atan(x).
  367.  *
  368.  *              (2)     If argument x > 1 at this point then
  369.  *                      test to be sure that x can be inverted
  370.  *                      without underflowing.  If not, reduce
  371.  *                      x to largest possible number that can
  372.  *                      be inverted, issue warning, and continue.
  373.  *                      Perform steps 3 and 4 with arg = 1/x
  374.  *                      and subtract returned result from
  375.  *                      pi/2.  This makes use of the identity
  376.  *                      atan(x) = pi/2 - atan(1/x) for x>0.
  377.  *
  378.  *              (3)     At this point 0 <= x <= 1.  If
  379.  *                      x > tan(pi/12) then perform step 4
  380.  *                      with arg = (x*sqrt(3)-1)/(sqrt(3)+x)
  381.  *                      and add pi/6 to returned result.  This
  382.  *                      last transformation maps arguments
  383.  *                      greater than tan(pi/12) to arguments
  384.  *                      in range 0...tan(pi/12).
  385.  *
  386.  *              (4)     At this point the argument has been
  387.  *                      transformed so that it lies in the
  388.  *                      range -tan(pi/12)...tan(pi/12).
  389.  *                      Since very small arguments may cause
  390.  *                      underflow in the polynomial evaluation,
  391.  *                      a final check is performed.  If the
  392.  *                      argument is less than the underflow
  393.  *                      bound, the function returns x, since
  394.  *                      atan(x) approaches asin(x) which
  395.  *                      approaches x, as x goes to zero.
  396.  *
  397.  *              (5)     atan(x) is now computed by one of the
  398.  *                      approximations given in the cited
  399.  *                      reference (Hart).  That is:
  400.  *
  401.  *                      atan(x) = x * SUM [ C[i] * x**(2*i) ]
  402.  *                      over i = {0,1,...8}.
  403.  *
  404.  *                      Where:
  405.  *
  406.  *                      C[0] =  .9999999999999999849899
  407.  *                      C[1] =  -.333333333333299308717
  408.  *                      C[2] =  .1999999999872944792
  409.  *                      C[3] =  -.142857141028255452
  410.  *                      C[4] =  .11111097898051048
  411.  *                      C[5] =  -.0909037114191074
  412.  *                      C[6] =  .0767936869066
  413.  *                      C[7] =  -.06483193510303
  414.  *                      C[8] =  .0443895157187
  415.  *                      (coefficients from HART table #4945 pg 267)
  416.  */
  417.  
  418. #ifdef   NEED_ATAN
  419.  
  420. #define  LAST_BOUND  0.2679491924311227074725     /*  tan (PI/12) */
  421.  
  422. static double atan_coeffs[] = {
  423.     .9999999999999999849899,                    /* P0 must be first     */
  424.     -.333333333333299308717,
  425.     .1999999999872944792,
  426.     -.142857141028255452,
  427.     .11111097898051048,
  428.     -.0909037114191074,
  429.     .0767936869066,
  430.     -.06483193510303,
  431.     .0443895157187                              /* Pn must be last      */
  432. } ;
  433.  
  434. double
  435. atan(x)
  436. double x ;
  437. {
  438.   register int order ;
  439.   double t1, t2, xt2 ;
  440.   auto double retval ;
  441.  
  442.   if (x < 0.0) retval = -(atan(-x)) ;
  443.   else if (x > 1.0)
  444.     {
  445.       if (x < MAXDOUBLE && x > -MAXDOUBLE)
  446.         retval = HALFPI - atan(1.0 / x) ;
  447.       else
  448.         {
  449.           doerr("atan", "UNDERFLOW", EDOM) ;
  450.           retval = 0.0 ;
  451.         }    
  452.     }
  453.   else if (x > LAST_BOUND)
  454.     {
  455.       t1 = x * SQRT3 - 1.0 ;
  456.       t2 = SQRT3 + x ;
  457.       retval = SIXTHPI + atan(t1 / t2) ;
  458.     }
  459.   else if (x < X16_UNDERFLOWS)
  460.     {
  461.       doerr("atan", "PLOSS", EDOM) ;
  462.       retval = x ;
  463.     }
  464.   else
  465.     {
  466.       xt2 = x * x ;
  467.       order = sizeof(atan_coeffs) / sizeof(double) ;
  468.       order -= 1 ;
  469.       retval = x * poly(order, atan_coeffs, xt2) ;
  470.     }
  471.   return(retval) ;
  472. }
  473. #endif /*NEED_ATAN*/
  474.  
  475.  
  476. /*  FUNCTION
  477.  *
  478.  *      atanh   double precision hyperbolic arc tangent
  479.  *
  480.  *  DESCRIPTION
  481.  *
  482.  *      Returns double precision hyperbolic arc tangent of double precision
  483.  *      floating point number.
  484.  *
  485.  *  USAGE
  486.  *
  487.  *      double atanh(x)
  488.  *      double x ;
  489.  *
  490.  *  RESTRICTIONS
  491.  *
  492.  *      The range of the atanh function is -1.0 to +1.0 exclusive.
  493.  *      Certain pathological cases near 1.0 may cause overflow
  494.  *      in evaluation of 1+x / 1-x, depending upon machine exponent
  495.  *      range and mantissa precision.
  496.  *
  497.  *      For precision information refer to documentation of the
  498.  *      other floating point library routines called.
  499.  *
  500.  *  INTERNALS
  501.  *
  502.  *      Computes atanh(x) from:
  503.  *
  504.  *              1.      If x <= -1.0 or x >= 1.0
  505.  *                      then report argument out of range and return 0.0
  506.  *
  507.  *              2.      atanh(x) = 0.5 * log((1+x)/(1-x))
  508.  */
  509.  
  510. #ifdef   NEED_ATANH
  511. double
  512. atanh(x)
  513. double x ;
  514. {
  515.   auto double retval ;
  516.  
  517.   if (x <= -1.0 || x >= 1.0)
  518.     {
  519.       doerr("atan", "DOMAIN", ERANGE) ;
  520.       retval = 0.0 ;
  521.     }
  522.   else retval = 0.5 * log((1+x) / (1-x)) ;
  523.   return(retval) ;
  524. }
  525. #endif /*NEED_ATANH*/
  526.  
  527.  
  528. /*  FUNCTION
  529.  *
  530.  *      cos  -  double precision cosine
  531.  *
  532.  *  DESCRIPTION
  533.  *
  534.  *      Returns double precision cosine of double precision
  535.  *      floating point argument.
  536.  *
  537.  *  USAGE
  538.  *
  539.  *      double cos(x)
  540.  *      double x ;
  541.  *
  542.  *  REFERENCES
  543.  *
  544.  *      Computer Approximations, J.F. Hart et al, John Wiley & Sons,
  545.  *      1968, pp. 112-120.
  546.  *
  547.  *  RESTRICTIONS
  548.  *
  549.  *      The sin and cos routines are interactive in the sense that
  550.  *      in the process of reducing the argument to the range -PI/4
  551.  *      to PI/4, each may call the other.  Ultimately one or the
  552.  *      other uses a polynomial approximation on the reduced
  553.  *      argument.  The sin approximation has a maximum relative error
  554.  *      of 10**(-17.59) and the cos approximation has a maximum
  555.  *      relative error of 10**(-16.18).
  556.  *
  557.  *      These error bounds assume exact arithmetic
  558.  *      in the polynomial evaluation.  Additional rounding and
  559.  *      truncation errors may occur as the argument is reduced
  560.  *      to the range over which the polynomial approximation
  561.  *      is valid, and as the polynomial is evaluated using
  562.  *      finite-precision arithmetic.
  563.  *
  564.  *  INTERNALS
  565.  *
  566.  *      Computes cos(x) from:
  567.  *
  568.  *              (1)     Reduce argument x to range -PI to PI.
  569.  *
  570.  *              (2)     If x > PI/2 then call cos recursively
  571.  *                      using relation cos(x) = -cos(x - PI).
  572.  *
  573.  *              (3)     If x < -PI/2 then call cos recursively
  574.  *                      using relation cos(x) = -cos(x + PI).
  575.  *
  576.  *              (4)     If x > PI/4 then call sin using
  577.  *                      relation cos(x) = sin(PI/2 - x).
  578.  *
  579.  *              (5)     If x < -PI/4 then call cos using
  580.  *                      relation cos(x) = sin(PI/2 + x).
  581.  *
  582.  *              (6)     If x would cause underflow in approx
  583.  *                      evaluation arithmetic then return
  584.  *                      sqrt(1.0 - x**2).
  585.  *
  586.  *              (7)     By now x has been reduced to range
  587.  *                      -PI/4 to PI/4 and the approximation
  588.  *                      from HART pg. 119 can be used:
  589.  *
  590.  *                      cos(x) = ( p(y) / q(y) )
  591.  *                      Where:
  592.  *
  593.  *                      y    =  x * (4/PI)
  594.  *
  595.  *                      p(y) =  SUM [ Pj * (y**(2*j)) ]
  596.  *                      over j = {0,1,2,3}
  597.  *
  598.  *                      q(y) =  SUM [ Qj * (y**(2*j)) ]
  599.  *                      over j = {0,1,2,3}
  600.  *
  601.  *                      P0   =  0.12905394659037374438571854e+7
  602.  *                      P1   =  -0.3745670391572320471032359e+6
  603.  *                      P2   =  0.134323009865390842853673e+5
  604.  *                      P3   =  -0.112314508233409330923e+3
  605.  *                      Q0   =  0.12905394659037373590295914e+7
  606.  *                      Q1   =  0.234677731072458350524124e+5
  607.  *                      Q2   =  0.2096951819672630628621e+3
  608.  *                      Q3   =  1.0000...
  609.  *                      (coefficients from HART table #3843 pg 244)
  610.  *
  611.  *
  612.  *      **** NOTE ****    The range reduction relations used in
  613.  *      this routine depend on the final approximation being valid
  614.  *      over the negative argument range in addition to the positive
  615.  *      argument range.  The particular approximation chosen from
  616.  *      HART satisfies this requirement, although not explicitly
  617.  *      stated in the text.  This may not be true of other
  618.  *      approximations given in the reference.
  619.  */
  620.  
  621. #ifdef   NEED_COS
  622.  
  623. static double cos_pcoeffs[] = {
  624.     0.12905394659037374438e7,
  625.    -0.37456703915723204710e6,
  626.     0.13432300986539084285e5,
  627.    -0.11231450823340933092e3
  628. } ;
  629.  
  630. static double cos_qcoeffs[] = {
  631.     0.12905394659037373590e7,
  632.     0.23467773107245835052e5,
  633.     0.20969518196726306286e3,
  634.     1.0
  635. } ;
  636.  
  637. double
  638. cos(x)
  639. double x ;
  640. {
  641.   auto double y, yt2 ;
  642.   auto double retval ;
  643.  
  644.   if (x < -PI || x > PI)
  645.     {
  646.       x = mod(x, TWOPI) ;
  647.            if (x > PI)  x = x - TWOPI ;
  648.       else if (x < -PI) x = x + TWOPI ;
  649.     }    
  650.        if (x > HALFPI)    retval = -(cos(x - PI)) ;
  651.   else if (x < -HALFPI)   retval = -(cos(x + PI)) ;
  652.   else if (x > FOURTHPI)  retval = sin(HALFPI - x) ;
  653.   else if (x < -FOURTHPI) retval = sin(HALFPI + x) ;
  654.   else if (x < X6_UNDERFLOWS && x > -X6_UNDERFLOWS)
  655.     retval = sqrt(1.0 - (x * x)) ;
  656.   else
  657.     {
  658.       y = x / FOURTHPI ;
  659.       yt2 = y * y ;
  660.       retval = poly(3, cos_pcoeffs, yt2) / poly(3, cos_qcoeffs, yt2) ;
  661.     }
  662.   return(retval) ;
  663. }
  664. #endif /*NEED_COS*/
  665.  
  666.  
  667. /*  FUNCTION
  668.  *
  669.  *      cosh   double precision hyperbolic cosine
  670.  *
  671.  *  DESCRIPTION
  672.  *
  673.  *      Returns double precision hyperbolic cosine of double precision
  674.  *      floating point number.
  675.  *
  676.  *  USAGE
  677.  *
  678.  *      double cosh(x)
  679.  *      double x ;
  680.  *
  681.  *  REFERENCES
  682.  *
  683.  *      Fortran IV plus user's guide, Digital Equipment Corp. pp B-4
  684.  *
  685.  *  RESTRICTIONS
  686.  *
  687.  *      Inputs greater than log(MAXDOUBLE) result in overflow.
  688.  *      Inputs less than log(MINDOUBLE) result in underflow.
  689.  *
  690.  *      For precision information refer to documentation of the
  691.  *      floating point library routines called.
  692.  *
  693.  *  INTERNALS
  694.  *
  695.  *      Computes hyperbolic cosine from:
  696.  *
  697.  *              cosh(X) = 0.5 * (exp(X) + exp(-X))
  698.  */
  699.  
  700.  
  701. #ifdef   NEED_COSH
  702. double
  703. cosh(x)
  704. double x ;
  705. {
  706.   auto double retval ;
  707.  
  708.   if (x > LOGE_MAXDOUBLE)
  709.     {
  710.       doerr("cosh", "OVERFLOW", ERANGE) ;
  711.       retval = MAXDOUBLE ;
  712.     }
  713.   else if (x < LOGE_MINDOUBLE)
  714.     {
  715.       doerr("cosh", "UNDERFLOW", ERANGE) ;
  716.       retval = MINDOUBLE ;
  717.     }
  718.   else
  719.     {
  720.       x = exp(x) ;
  721.       retval = 0.5 * (x + 1.0 / x) ;
  722.     }
  723.   return(retval) ;
  724. }
  725. #endif /*NEED_COSH*/
  726.  
  727.  
  728. /*  FUNCTION
  729.  *
  730.  *      dabs   double precision absolute value
  731.  *
  732.  *  DESCRIPTION
  733.  *
  734.  *      Returns absolute value of double precision number.
  735.  *
  736.  *  USAGE
  737.  *
  738.  *      double dabs(x)
  739.  *      double x ;
  740.  */
  741.  
  742. #ifdef   NEED_EXP
  743. double
  744. dabs(x)
  745. double x ;
  746. {
  747.   if (x < 0.0) x = -x ;
  748.   return(x) ;
  749. }
  750. #endif /*NEED_EXP*/
  751.  
  752.  
  753. /*  FUNCTION
  754.  *
  755.  *      exp   double precision exponential
  756.  *
  757.  *  DESCRIPTION
  758.  *
  759.  *      Returns double precision exponential of double precision
  760.  *      floating point number.
  761.  *
  762.  *  USAGE
  763.  *
  764.  *      double exp(x)
  765.  *      double x ;
  766.  *
  767.  *  REFERENCES
  768.  *
  769.  *      Fortran IV plus user's guide, Digital Equipment Corp. pp B-3
  770.  *
  771.  *      Computer Approximations, J.F. Hart et al, John Wiley & Sons,
  772.  *      1968, pp. 96-104.
  773.  *
  774.  *  RESTRICTIONS
  775.  *
  776.  *      Inputs greater than log(MAXDOUBLE) result in overflow.
  777.  *      Inputs less than log(MINDOUBLE) result in underflow.
  778.  *
  779.  *      The maximum relative error for the approximating polynomial
  780.  *      is 10**(-16.4).  However, this assumes exact arithmetic
  781.  *      in the polynomial evaluation.  Additional rounding and
  782.  *      truncation errors may occur as the argument is reduced
  783.  *      to the range over which the polynomial approximation
  784.  *      is valid, and as the polynomial is evaluated using
  785.  *      finite precision arithmetic.
  786.  *
  787.  *
  788.  *  INTERNALS
  789.  *
  790.  *      Computes exponential from:
  791.  *
  792.  *              exp(x)  =       2**y  *  2**z  *  2**w
  793.  *
  794.  *      Where:
  795.  *
  796.  *              y       =       int ( x * log2(e) )
  797.  *
  798.  *              v       =       16 * frac ( x * log2(e))
  799.  *
  800.  *              z       =       (1/16) * int (v)
  801.  *
  802.  *              w       =       (1/16) * frac (v)
  803.  *
  804.  *      Note that:
  805.  *
  806.  *              0 =< v < 16
  807.  *
  808.  *              z = {0, 1/16, 2/16, ...15/16}
  809.  *
  810.  *              0 =< w < 1/16
  811.  *
  812.  *      Then:
  813.  *
  814.  *              2**z is looked up in a table of 2**0, 2**1/16, ...
  815.  *
  816.  *              2**w is computed from an approximation:
  817.  *
  818.  *                      2**w    =  (A + B) / (A - B)
  819.  *
  820.  *                      A       =  C + (D * w * w)
  821.  *
  822.  *                      B       =  w * (E + (F * w * w))
  823.  *
  824.  *                      C       =  20.8137711965230361973
  825.  *
  826.  *                      D       =  1.0
  827.  *
  828.  *                      E       =  7.2135034108448192083
  829.  *
  830.  *                      F       =  0.057761135831801928
  831.  *
  832.  *              Coefficients are from HART, table #1121, pg 206.
  833.  *
  834.  *              Effective multiplication by 2**y is done by a
  835.  *              floating point scale with y as scale argument.
  836.  */
  837.  
  838. #ifdef   NEED_EXP
  839.  
  840. #define  C           20.8137711965230361973   /* Polynomial approx coeff. */
  841. #define  D           1.0                      /* Polynomial approx coeff. */
  842. #define  E           7.2135034108448192083    /* Polynomial approx coeff. */
  843. #define  F           0.057761135831801928     /* Polynomial approx coeff. */
  844.  
  845. /************************************************************************
  846.  *                                                                      *
  847.  *      This table is fixed in size and reasonably hardware             *
  848.  *      independent.  The given constants were generated on a           *
  849.  *      DECSYSTEM 20 using double precision FORTRAN.                    *
  850.  *                                                                      *
  851.  ************************************************************************
  852.  */
  853.  
  854. static double fpof2tbl[] = {
  855.     1.00000000000000000000,             /* 2 ** 0/16  */
  856.     1.04427378242741384020,             /* 2 ** 1/16  */
  857.     1.09050773266525765930,             /* 2 ** 2/16  */
  858.     1.13878863475669165390,             /* 2 ** 3/16  */
  859.     1.18920711500272106640,             /* 2 ** 4/16  */
  860.     1.24185781207348404890,             /* 2 ** 5/16  */
  861.     1.29683955465100966610,             /* 2 ** 6/16  */
  862.     1.35425554693689272850,             /* 2 ** 7/16  */
  863.     1.41421356237309504880,             /* 2 ** 8/16  */
  864.     1.47682614593949931110,             /* 2 ** 9/16  */
  865.     1.54221082540794082350,             /* 2 ** 10/16 */
  866.     1.61049033194925430820,             /* 2 ** 11/16 */
  867.     1.68179283050742908600,             /* 2 ** 12/16 */
  868.     1.75625216037329948340,             /* 2 ** 13/16 */
  869.     1.83400808640934246360,             /* 2 ** 14/16 */
  870.     1.91520656139714729380              /* 2 ** 15/16 */
  871. } ;
  872.  
  873. double
  874. exp(x)
  875. double x ;
  876. {
  877.   register int ival, y ;
  878.   auto double a, b, rtnval, t, temp, v, w, wpof2, zpof2 ;
  879.   auto double retval ;
  880.  
  881.   if (x > LOGE_MAXDOUBLE)
  882.     {
  883.       doerr("exp", "OVERFLOW", ERANGE) ;
  884.       retval = MAXDOUBLE ;
  885.     }
  886.   else if (x <= LOGE_MINDOUBLE)
  887.     {
  888.       doerr("exp", "UNDERFLOW", ERANGE) ;
  889.       retval = 0.0 ;
  890.     }
  891.    else
  892.     {
  893.       t = x * LOG2E ;
  894.       (void) modf(t, &temp) ;
  895.       y = temp ;
  896.       v = 16.0 * modf(t, &temp) ;
  897.       (void) modf(dabs(v), &temp) ;
  898.       ival = temp ;
  899.       if (x < 0.0) zpof2 = 1.0 / fpof2tbl[ival] ;
  900.       else         zpof2 = fpof2tbl[ival] ;
  901.       w = modf(v, &temp) / 16.0 ;
  902.       a = C + (D * w * w) ;
  903.       b = w * (E + (F * w * w)) ;
  904.       wpof2 = (a + b) / (a - b) ;
  905.       retval = ldexp((wpof2 * zpof2), y) ;
  906.     }
  907.   return(retval) ;
  908. }
  909. #endif /*NEED_EXP*/
  910.  
  911.  
  912. /*  FUNCTION
  913.  *
  914.  *      log   double precision natural log
  915.  *
  916.  *  DESCRIPTION
  917.  *
  918.  *      Returns double precision natural log of double precision
  919.  *      floating point argument.
  920.  *
  921.  *  USAGE
  922.  *
  923.  *      double log(x)
  924.  *      double x ;
  925.  *
  926.  *  REFERENCES
  927.  *
  928.  *      Computer Approximations, J.F. Hart et al, John Wiley & Sons,
  929.  *      1968, pp. 105-111.
  930.  *
  931.  *  RESTRICTIONS
  932.  *
  933.  *      The absolute error in the approximating polynomial is
  934.  *      10**(-19.38).  Note that contrary to DEC's assertion
  935.  *      in the F4P user's guide, the error is absolute and not
  936.  *      relative.
  937.  *
  938.  *      This error bound assumes exact arithmetic
  939.  *      in the polynomial evaluation.  Additional rounding and
  940.  *      truncation errors may occur as the argument is reduced
  941.  *      to the range over which the polynomial approximation
  942.  *      is valid, and as the polynomial is evaluated using
  943.  *      finite-precision arithmetic.
  944.  *
  945.  *  INTERNALS
  946.  *
  947.  *      Computes log(X) from:
  948.  *
  949.  *        (1)   If argument is zero then flag an error
  950.  *              and return minus infinity (or rather its
  951.  *              machine representation).
  952.  *
  953.  *        (2)   If argument is negative then flag an
  954.  *              error and return minus infinity.
  955.  *
  956.  *        (3)   Given that x = m * 2**k then extract
  957.  *              mantissa m and exponent k.
  958.  *
  959.  *        (4)   Transform m which is in range [0.5,1.0]
  960.  *              to range [1/sqrt(2), sqrt(2)] by:
  961.  *
  962.  *                      s = m * sqrt(2)
  963.  *
  964.  *        (5)   Compute z = (s - 1) / (s + 1)
  965.  *
  966.  *        (6)   Now use the approximation from HART
  967.  *              page 111 to find log(s):
  968.  *
  969.  *              log(s) = z * ( P(z**2) / Q(z**2) )
  970.  *
  971.  *              Where:
  972.  *
  973.  *              P(z**2) =  SUM [ Pj * (z**(2*j)) ]
  974.  *              over j = {0,1,2,3}
  975.  *
  976.  *              Q(z**2) =  SUM [ Qj * (z**(2*j)) ]
  977.  *              over j = {0,1,2,3}
  978.  *
  979.  *              P0 =  -0.240139179559210509868484e2
  980.  *              P1 =  0.30957292821537650062264e2
  981.  *              P2 =  -0.96376909336868659324e1
  982.  *              P3 =  0.4210873712179797145
  983.  *              Q0 =  -0.120069589779605254717525e2
  984.  *              Q1 =  0.19480966070088973051623e2
  985.  *              Q2 =  -0.89111090279378312337e1
  986.  *              Q3 =  1.0000
  987.  *
  988.  *              (coefficients from HART table #2705 pg 229)
  989.  *
  990.  *        (7)   Finally, compute log(x) from:
  991.  *
  992.  *              log(x) = (k * log(2)) - log(sqrt(2)) + log(s)
  993.  */
  994.  
  995. #ifdef   NEED_LOG
  996.  
  997. static double log_pcoeffs[] = {
  998.    -0.24013917955921050986e2,
  999.     0.30957292821537650062e2,
  1000.    -0.96376909336868659324e1,
  1001.     0.4210873712179797145
  1002. } ;
  1003.  
  1004. static double log_qcoeffs[] = {
  1005.    -0.12006958977960525471e2,
  1006.     0.19480966070088973051e2,
  1007.    -0.89111090279378312337e1,
  1008.     1.0000
  1009. } ;
  1010.  
  1011. double
  1012. log(x)
  1013. double x ;
  1014. {
  1015.   auto int k ;
  1016.   auto double pqofz, s, z, zt2 ;
  1017.   auto double retval ;
  1018.  
  1019.   if (x == 0.0)
  1020.     {
  1021.       doerr("log", "SINGULARITY", EDOM) ;
  1022.       retval = -MAXDOUBLE ;
  1023.     }
  1024.   else if (x < 0.0)
  1025.     {
  1026.       doerr("log", "DOMAIN", EDOM) ;
  1027.       retval = -MAXDOUBLE ;
  1028.     }
  1029.   else
  1030.     {
  1031.       s = SQRT2 * frexp(x, &k) ;
  1032.       z = (s - 1.0) / (s + 1.0) ;
  1033.       zt2 = z * z ;
  1034.       pqofz = z * (poly(3, log_pcoeffs, zt2) / poly(3, log_qcoeffs, zt2)) ;
  1035.       x = k * LN2 ;
  1036.       x -= LNSQRT2 ;
  1037.       x += pqofz ;
  1038.       retval = x ;
  1039.     }
  1040.   return(retval) ;
  1041. }
  1042. #endif /*NEED_LOG*/
  1043.  
  1044.  
  1045. /*  FUNCTION
  1046.  *
  1047.  *      log10   double precision common log
  1048.  *
  1049.  *  DESCRIPTION
  1050.  *
  1051.  *      Returns double precision common log of double precision
  1052.  *      floating point argument.
  1053.  *
  1054.  *  USAGE
  1055.  *
  1056.  *      double log10(x)
  1057.  *      double x ;
  1058.  *
  1059.  *  REFERENCES
  1060.  *
  1061.  *      PDP-11 Fortran IV-plus users guide, Digital Equip. Corp.,
  1062.  *      1975, pp. B-3.
  1063.  *
  1064.  *  RESTRICTIONS
  1065.  *
  1066.  *      For precision information refer to documentation of the
  1067.  *      floating point library routines called.
  1068.  *
  1069.  *  INTERNALS
  1070.  *
  1071.  *      Computes log10(x) from:
  1072.  *
  1073.  *              log10(x) = log10(e) * log(x)
  1074.  */
  1075.  
  1076. #ifdef   NEED_LOG10
  1077. double
  1078. log10(x)
  1079. double x ;
  1080. {
  1081.   x = LOG10E * log(x) ;
  1082.   return(x) ;
  1083. }
  1084. #endif /*NEED_LOG10*/
  1085.  
  1086.  
  1087. /*  FUNCTION
  1088.  *
  1089.  *      mod   double precision modulo
  1090.  *
  1091.  *  DESCRIPTION
  1092.  *
  1093.  *      Returns double precision modulo of two double
  1094.  *      precision arguments.
  1095.  *
  1096.  *  USAGE
  1097.  *
  1098.  *      double mod(value, base)
  1099.  *      double value ;
  1100.  *      double base ;
  1101.  */
  1102.  
  1103. #if defined (NEED_COS) || defined (NEED_SIN)
  1104. double mod(value, base)
  1105. double value ;
  1106. double base ;
  1107. {
  1108.   auto double intpart ;
  1109.  
  1110.   value /= base ;
  1111.   value = modf(value, &intpart) ;
  1112.   value *= base ;
  1113.   return(value) ;
  1114. }
  1115. #endif /*NEED_COS || NEED_SIN*/
  1116.  
  1117.  
  1118. /*  FUNCTION
  1119.  *
  1120.  *      poly   double precision polynomial evaluation
  1121.  *
  1122.  *  DESCRIPTION
  1123.  *
  1124.  *      Evaluates a polynomial and returns double precision
  1125.  *      result.  Is passed a the order of the polynomial,
  1126.  *      a pointer to an array of double precision polynomial
  1127.  *      coefficients (in ascending order), and the independent
  1128.  *      variable.
  1129.  *
  1130.  *  USAGE
  1131.  *
  1132.  *      double poly(order, coeffs, x)
  1133.  *      int order ;
  1134.  *      double *coeffs ;
  1135.  *      double x ;
  1136.  *
  1137.  *  INTERNALS
  1138.  *
  1139.  *      Evalates the polynomial using recursion and the form:
  1140.  *
  1141.  *              P(x) = P0 + x(P1 + x(P2 +...x(Pn)))
  1142.  */
  1143.  
  1144. #if defined (NEED_ATAN) || defined (NEED_COS) || defined (NEED_LOG) || defined (NEED_SIN)
  1145. double
  1146. poly(order, coeffs, x)
  1147. register int order ;
  1148. double *coeffs ;
  1149. double x ;
  1150. {
  1151.   auto double curr_coeff, rtn_value ;
  1152.  
  1153.   if (order <= 0) rtn_value = *coeffs ;
  1154.   else
  1155.     {
  1156.       curr_coeff = *coeffs ;   /* Bug in Unisoft's compiler.  Does not */
  1157.       coeffs++ ;               /* generate good code for *coeffs++ */
  1158.       rtn_value = curr_coeff + x * poly(--order, coeffs, x) ;
  1159.     }
  1160.   return(rtn_value) ;
  1161. }
  1162. #endif /*NEED_ATAN || NEED_COS || NEED_LOG || NEED_SIN*/
  1163.  
  1164.  
  1165. /*  FUNCTION
  1166.  *
  1167.  *  sin  double precision sine
  1168.  *
  1169.  *  DESCRIPTION
  1170.  *
  1171.  *  Returns double precision sine of double precision
  1172.  *  floating point argument.
  1173.  *
  1174.  *  USAGE
  1175.  *
  1176.  *  double sin(x)
  1177.  *  double x ;
  1178.  *
  1179.  *  REFERENCES
  1180.  *
  1181.  *  Computer Approximations, J.F. Hart et al, John Wiley & Sons,
  1182.  *  1968, pp. 112-120.
  1183.  *
  1184.  *  RESTRICTIONS
  1185.  *
  1186.  *  The sin and cos routines are interactive in the sense that
  1187.  *  in the process of reducing the argument to the range -PI/4
  1188.  *  to PI/4, each may call the other.  Ultimately one or the
  1189.  *  other uses a polynomial approximation on the reduced
  1190.  *  argument.  The sin approximation has a maximum relative error
  1191.  *  of 10**(-17.59) and the cos approximation has a maximum
  1192.  *  relative error of 10**(-16.18).
  1193.  *
  1194.  *  These error bounds assume exact arithmetic
  1195.  *  in the polynomial evaluation.  Additional rounding and
  1196.  *  truncation errors may occur as the argument is reduced
  1197.  *  to the range over which the polynomial approximation
  1198.  *  is valid, and as the polynomial is evaluated using
  1199.  *  finite-precision arithmetic.
  1200.  *  
  1201.  *  INTERNALS
  1202.  *
  1203.  *  Computes sin(x) from:
  1204.  *
  1205.  *    (1)  Reduce argument x to range -PI to PI.
  1206.  *
  1207.  *    (2)  If x > PI/2 then call sin recursively
  1208.  *    using relation sin(x) = -sin(x - PI).
  1209.  *
  1210.  *    (3)  If x < -PI/2 then call sin recursively
  1211.  *    using relation sin(x) = -sin(x + PI).
  1212.  *
  1213.  *    (4)  If x > PI/4 then call cos using
  1214.  *    relation sin(x) = cos(PI/2 - x).
  1215.  *
  1216.  *    (5)  If x < -PI/4 then call cos using
  1217.  *    relation sin(x) = -cos(PI/2 + x).
  1218.  *
  1219.  *    (6)  If x is small enough that polynomial
  1220.  *    evaluation would cause underflow
  1221.  *    then return x, since sin(x)
  1222.  *    approaches x as x approaches zero.
  1223.  *
  1224.  *    (7)  By now x has been reduced to range
  1225.  *    -PI/4 to PI/4 and the approximation
  1226.  *    from HART pg. 118 can be used:
  1227.  *
  1228.  *    sin(x) = y * ( p(y) / q(y) )
  1229.  *    Where:
  1230.  *
  1231.  *    y    =  x * (4/PI)
  1232.  *
  1233.  *    p(y) =  SUM [ Pj * (y**(2*j)) ]
  1234.  *    over j = {0,1,2,3}
  1235.  *
  1236.  *    q(y) =  SUM [ Qj * (y**(2*j)) ]
  1237.  *    over j = {0,1,2,3}
  1238.  *
  1239.  *    P0   =  0.206643433369958582409167054e+7
  1240.  *    P1   =  -0.18160398797407332550219213e+6
  1241.  *    P2   =  0.359993069496361883172836e+4
  1242.  *    P3   =  -0.2010748329458861571949e+2
  1243.  *    Q0   =  0.263106591026476989637710307e+7
  1244.  *    Q1   =  0.3927024277464900030883986e+5
  1245.  *    Q2   =  0.27811919481083844087953e+3
  1246.  *    Q3   =  1.0000...
  1247.  *    (coefficients from HART table #3063 pg 234)
  1248.  *
  1249.  *
  1250.  *  **** NOTE ****    The range reduction relations used in
  1251.  *  this routine depend on the final approximation being valid
  1252.  *  over the negative argument range in addition to the positive
  1253.  *  argument range.  The particular approximation chosen from
  1254.  *  HART satisfies this requirement, although not explicitly
  1255.  *  stated in the text.  This may not be true of other
  1256.  *  approximations given in the reference.
  1257.  */
  1258.  
  1259. #ifdef   NEED_SIN
  1260.  
  1261. static double sin_pcoeffs[] = {
  1262.     0.20664343336995858240e7,
  1263.    -0.18160398797407332550e6,
  1264.     0.35999306949636188317e4,
  1265.    -0.20107483294588615719e2
  1266. } ;
  1267.  
  1268. static double sin_qcoeffs[] = {
  1269.     0.26310659102647698963e7,
  1270.     0.39270242774649000308e5,
  1271.     0.27811919481083844087e3,
  1272.     1.0
  1273. } ;
  1274.  
  1275. double
  1276. sin(x)
  1277. double x ;
  1278. {
  1279.   double y, yt2 ;
  1280.   auto double retval ;
  1281.  
  1282.   if (x < -PI || x > PI)
  1283.     {
  1284.       x = mod(x, TWOPI) ;
  1285.            if (x > PI)  x = x - TWOPI ;
  1286.       else if (x < -PI) x = x + TWOPI ;
  1287.     }
  1288.        if (x > HALFPI)    retval = -(sin(x - PI)) ;
  1289.   else if (x < -HALFPI)   retval = -(sin(x + PI)) ;
  1290.   else if (x > FOURTHPI)  retval = cos(HALFPI - x) ;
  1291.   else if (x < -FOURTHPI) retval = -(cos(HALFPI + x)) ;
  1292.   else if (x < X6_UNDERFLOWS && x > -X6_UNDERFLOWS) retval = x ;
  1293.   else
  1294.     {
  1295.       y = x / FOURTHPI ;
  1296.       yt2 = y * y ;
  1297.       retval = y * (poly(3, sin_pcoeffs, yt2) / poly(3, sin_qcoeffs, yt2)) ;
  1298.     }
  1299.   return(retval) ;
  1300. }
  1301. #endif /*NEED_SIN*/
  1302.  
  1303.  
  1304. /*  FUNCTION
  1305.  *
  1306.  *      sinh   double precision hyperbolic sine
  1307.  *
  1308.  *  DESCRIPTION
  1309.  *
  1310.  *      Returns double precision hyperbolic sine of double precision
  1311.  *      floating point number.
  1312.  *
  1313.  *  USAGE
  1314.  *
  1315.  *      double sinh(x)
  1316.  *      double x ;
  1317.  *
  1318.  *  REFERENCES
  1319.  *
  1320.  *      Fortran IV plus user's guide, Digital Equipment Corp. pp B-5
  1321.  *
  1322.  *  RESTRICTIONS
  1323.  *
  1324.  *      Inputs greater than ln(MAXDOUBLE) result in overflow.
  1325.  *      Inputs less than ln(MINDOUBLE) result in underflow.
  1326.  *
  1327.  *      For precision information refer to documentation of the
  1328.  *      floating point library routines called.
  1329.  *
  1330.  *  INTERNALS
  1331.  *
  1332.  *      Computes hyperbolic sine from:
  1333.  *
  1334.  *              sinh(x) = 0.5 * (exp(x) - 1.0/exp(x))
  1335.  */
  1336.  
  1337. #ifdef   NEED_SINH
  1338. double
  1339. sinh(x)
  1340. double x ;
  1341. {
  1342.   auto double retval ;
  1343.  
  1344.   if (x > LOGE_MAXDOUBLE)
  1345.     {
  1346.       doerr("sinh", "OVERFLOW", ERANGE) ;
  1347.       retval = MAXDOUBLE ;
  1348.     }
  1349.   else if (x < LOGE_MINDOUBLE)
  1350.     {
  1351.       doerr("sinh", "UNDERFLOW", ERANGE) ;
  1352.       retval = MINDOUBLE ;
  1353.     }
  1354.   else
  1355.     {
  1356.       x = exp(x) ;
  1357.       retval = 0.5 * (x - (1.0 / x)) ;
  1358.     }
  1359.   return(retval) ;
  1360. }
  1361. #endif /*NEED_SINH*/
  1362.  
  1363.  
  1364. /*  FUNCTION
  1365.  *
  1366.  *      sqrt   double precision square root
  1367.  *
  1368.  *  DESCRIPTION
  1369.  *
  1370.  *      Returns double precision square root of double precision
  1371.  *      floating point argument.
  1372.  *
  1373.  *  USAGE
  1374.  *
  1375.  *      double sqrt(x)
  1376.  *      double x ;
  1377.  *
  1378.  *  REFERENCES
  1379.  *
  1380.  *      Fortran IV-PLUS user's guide, Digital Equipment Corp. pp B-7.
  1381.  *
  1382.  *      Computer Approximations, J.F. Hart et al, John Wiley & Sons,
  1383.  *      1968, pp. 89-96.
  1384.  *
  1385.  *  RESTRICTIONS
  1386.  *
  1387.  *      The relative error is 10**(-30.1) after three applications
  1388.  *      of Heron's iteration for the square root.
  1389.  *
  1390.  *      However, this assumes exact arithmetic in the iterations
  1391.  *      and initial approximation.  Additional errors may occur
  1392.  *      due to truncation, rounding, or machine precision limits.
  1393.  *
  1394.  *  INTERNALS
  1395.  *
  1396.  *      Computes square root by:
  1397.  *
  1398.  *        (1)   Range reduction of argument to [0.5,1.0]
  1399.  *              by application of identity:
  1400.  *
  1401.  *              sqrt(x)  =  2**(k/2) * sqrt(x * 2**(-k))
  1402.  *
  1403.  *              k is the exponent when x is written as
  1404.  *              a mantissa times a power of 2 (m * 2**k).
  1405.  *              It is assumed that the mantissa is
  1406.  *              already normalized (0.5 =< m < 1.0).
  1407.  *
  1408.  *        (2)   An approximation to sqrt(m) is obtained
  1409.  *              from:
  1410.  *
  1411.  *              u = sqrt(m) = (P0 + P1*m) / (Q0 + Q1*m)
  1412.  *
  1413.  *              P0 = 0.594604482
  1414.  *              P1 = 2.54164041
  1415.  *              Q0 = 2.13725758
  1416.  *              Q1 = 1.0
  1417.  *
  1418.  *              (coefficients from HART table #350 pg 193)
  1419.  *
  1420.  *        (3)   Three applications of Heron's iteration are
  1421.  *              performed using:
  1422.  *
  1423.  *              y[n+1] = 0.5 * (y[n] + (m/y[n]))
  1424.  *
  1425.  *              where y[0] = u = approx sqrt(m)
  1426.  *
  1427.  *        (4)   If the value of k was odd then y is either
  1428.  *              multiplied by the square root of two or
  1429.  *              divided by the square root of two for k positive
  1430.  *              or negative respectively.  This rescales y
  1431.  *              by multiplying by 2**frac(k/2).
  1432.  *
  1433.  *        (5)   Finally, y is rescaled by int(k/2) which
  1434.  *              is equivalent to multiplication by 2**int(k/2).
  1435.  *
  1436.  *              The result of steps 4 and 5 is that the value
  1437.  *              of y between 0.5 and 1.0 has been rescaled by
  1438.  *              2**(k/2) which removes the original rescaling
  1439.  *              done prior to finding the mantissa square root.
  1440.  *
  1441.  *  NOTES
  1442.  *
  1443.  *      The Convergent Technologies compiler optimizes division
  1444.  *      by powers of two to "arithmetic shift right" instructions.
  1445.  *      This is ok for positive integers but gives different
  1446.  *      results than other C compilers for negative integers.
  1447.  *      For example, (-1)/2 is -1 on the CT box, 0 on every other
  1448.  *      machine I tried.
  1449.  */
  1450.  
  1451. #ifdef   NEED_SQRT
  1452.  
  1453. #define  ITERATIONS  3                        /* Number of iterations */
  1454. #define  P0          0.594604482              /* Approximation coeff  */
  1455. #define  P1          2.54164041               /* Approximation coeff  */
  1456. #define  Q0          2.13725758               /* Approximation coeff  */
  1457. #define  Q1          1.0                      /* Approximation coeff  */
  1458.  
  1459. double
  1460. sqrt(x)
  1461. double x ;
  1462. {
  1463.   register int bugfix, count, kmod2 ;
  1464.   auto int exponent, k ;
  1465.   auto double m, u, y ;
  1466.   auto double retval ;
  1467.   
  1468.   if (x == 0.0) retval = 0.0 ;
  1469.   else if (x < 0.0)
  1470.     {
  1471.       doerr("sqrt", "DOMAIN", EDOM) ;
  1472.       retval = 0.0 ;
  1473.     }
  1474.   else
  1475.     {
  1476.       m = frexp(x, &k) ;
  1477.       u = (P0 + (P1 * m)) / (Q0 + (Q1 * m)) ;
  1478.       for (count = 0, y = u; count < ITERATIONS; count++)
  1479.         y = 0.5 * (y + (m / y)) ;
  1480.            if ((kmod2 = (k % 2)) < 0) y /= SQRT2 ;
  1481.       else if (kmod2 > 0)             y *= SQRT2 ;
  1482.       bugfix = 2 ;
  1483.       retval = ldexp(y, k / bugfix) ;
  1484.     }
  1485.   return(retval) ;
  1486. }
  1487. #endif /*NEED_SQRT*/
  1488.  
  1489.  
  1490. /*  FUNCTION
  1491.  *
  1492.  *      tan   Double precision tangent
  1493.  *
  1494.  *  DESCRIPTION
  1495.  *
  1496.  *      Returns tangent of double precision floating point number.
  1497.  *
  1498.  *  USAGE
  1499.  *
  1500.  *      double tan(x)
  1501.  *      double x ;
  1502.  *
  1503.  *  INTERNALS
  1504.  *
  1505.  *      Computes the tangent from tan(x) = sin(x) / cos(x).
  1506.  *
  1507.  *      If cos(x) = 0 and sin(x) >= 0, then returns largest
  1508.  *      floating point number on host machine.
  1509.  *
  1510.  *      If cos(x) = 0 and sin(x) < 0, then returns smallest
  1511.  *      floating point number on host machine.
  1512.  *
  1513.  *  REFERENCES
  1514.  *
  1515.  *      Fortran IV plus user's guide, Digital Equipment Corp. pp. B-8
  1516.  */
  1517.  
  1518. #ifdef   NEED_TAN
  1519. double
  1520. tan(x)
  1521. double x ;
  1522. {
  1523.   double cosx, sinx ;
  1524.   auto double retval ;
  1525.  
  1526.   sinx = sin(x) ;
  1527.   cosx = cos(x) ;
  1528.   if (cosx == 0.0)
  1529.     {
  1530.       doerr("tan", "OVERFLOW", ERANGE) ;
  1531.       if (sinx >= 0.0) retval = MAXDOUBLE ;
  1532.       else             retval = -MAXDOUBLE ;
  1533.     }
  1534.   else retval = sinx / cosx ;
  1535.   return(retval) ;
  1536. }
  1537. #endif /*NEED_TAN*/
  1538.  
  1539.  
  1540. /*  FUNCTION
  1541.  *
  1542.  *  tanh   double precision hyperbolic tangent
  1543.  *
  1544.  *  DESCRIPTION
  1545.  *
  1546.  *  Returns double precision hyperbolic tangent of double precision
  1547.  *  floating point number.
  1548.  *
  1549.  *  USAGE
  1550.  *
  1551.  *  double tanh(x)
  1552.  *  double x ;
  1553.  *
  1554.  *  REFERENCES
  1555.  *
  1556.  *  Fortran IV plus user's guide, Digital Equipment Corp. pp B-5
  1557.  *
  1558.  *  RESTRICTIONS
  1559.  *
  1560.  *  For precision information refer to documentation of the
  1561.  *  floating point library routines called.
  1562.  *  
  1563.  *  INTERNALS
  1564.  *
  1565.  *  Computes hyperbolic tangent from:
  1566.  *
  1567.  *    tanh(x) = 1.0 for x > TANH_MAXARG
  1568.  *      = -1.0 for x < -TANH_MAXARG
  1569.  *      =  sinh(x) / cosh(x) otherwise
  1570.  */
  1571.  
  1572. #ifdef   NEED_TANH
  1573. double
  1574. tanh(x)
  1575. double x ;
  1576. {
  1577.   auto double retval ;
  1578.   register int positive ;
  1579.  
  1580.   if (x > TANH_MAXARG || x < -TANH_MAXARG)
  1581.     {
  1582.       if (x > 0.0) positive = 1 ;
  1583.       else positive = 0 ;
  1584.       doerr("tanh", "PLOSS", ERANGE) ;
  1585.       if (positive) retval = 1.0 ;
  1586.       else          retval = -1.0 ;
  1587.     }
  1588.   else retval = sinh(x) / cosh(x) ;
  1589.   return(retval) ;
  1590. }
  1591. #endif   /*NEED_TANH*/
  1592.  
  1593.  
  1594. /*
  1595.  * Copyright (c) 1985 Regents of the University of California.
  1596.  * All rights reserved.
  1597.  *
  1598.  * Redistribution and use in source and binary forms are permitted
  1599.  * provided that the above copyright notice and this paragraph are
  1600.  * duplicated in all such forms and that any documentation,
  1601.  * advertising materials, and other materials related to such
  1602.  * distribution and use acknowledge that the software was developed
  1603.  * by the University of California, Berkeley.  The name of the
  1604.  * University may not be used to endorse or promote products derived
  1605.  * from this software without specific prior written permission.
  1606.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1607.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1608.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1609.  *
  1610.  * All recipients should regard themselves as participants in an ongoing
  1611.  * research project and hence should feel obligated to report their
  1612.  * experiences (good or bad) with these elementary function codes, using
  1613.  * the sendbug(8) program, to the authors.
  1614.  */
  1615.  
  1616. #ifdef   NEED_POW
  1617. /* POW(X,Y)
  1618.  * RETURN X**Y
  1619.  * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
  1620.  * CODED IN C BY K.C. NG, 1/8/85;
  1621.  * REVISED BY K.C. NG on 7/10/85.
  1622.  *
  1623.  * Required system supported functions:
  1624.  *      scalb(x,n)
  1625.  *      logb(x)
  1626.  *      copysign(x,y)
  1627.  *      finite(x)
  1628.  *      drem(x,y)
  1629.  *
  1630.  * Required kernel functions:
  1631.  *      exp__E(a, c)    ...return  exp(a+c) - 1 - a*a/2
  1632.  *      log__L(x)       ...return  (log(1+x) - 2s)/s, s=x/(2+x)
  1633.  *      pow_p(x, y)     ...return  +(anything)**(finite non zero)
  1634.  *
  1635.  * Method
  1636.  *      1. Compute and return log(x) in three pieces:
  1637.  *              log(x) = n*ln2 + hi + lo,
  1638.  *         where n is an integer.
  1639.  *      2. Perform y * log(x) by simulating muti-precision arithmetic and
  1640.  *         return the answer in three pieces:
  1641.  *              y * log(x) = m * ln2 + hi + lo,
  1642.  *         where m is an integer.
  1643.  *      3. Return x ** y = exp(y * log(x))
  1644.  *              = 2^m * (exp(hi + lo)).
  1645.  *
  1646.  * Special cases:
  1647.  *      (anything) ** 0  is 1 ;
  1648.  *      (anything) ** 1  is itself;
  1649.  *      (anything) ** NaN is NaN;
  1650.  *      NaN ** (anything except 0) is NaN;
  1651.  *      +-(anything > 1) ** +INF is +INF;
  1652.  *      +-(anything > 1) ** -INF is +0;
  1653.  *      +-(anything < 1) ** +INF is +0;
  1654.  *      +-(anything < 1) ** -INF is +INF;
  1655.  *      +-1 ** +-INF is NaN and signal INVALID;
  1656.  *      +0 ** +(anything except 0, NaN)  is +0;
  1657.  *      -0 ** +(anything except 0, NaN, odd integer)  is +0;
  1658.  *      +0 ** -(anything except 0, NaN)  is +INF and signal DIV-BY-ZERO;
  1659.  *      -0 ** -(anything except 0, NaN, odd integer)  is +INF with signal;
  1660.  *      -0 ** (odd integer) = -( +0 ** (odd integer) );
  1661.  *      +INF ** +(anything except 0,NaN) is +INF;
  1662.  *      +INF ** -(anything except 0,NaN) is +0;
  1663.  *      -INF ** (odd integer) = -( +INF ** (odd integer) );
  1664.  *      -INF ** (even integer) = ( +INF ** (even integer) );
  1665.  *      -INF ** -(anything except integer,NaN) is NaN with signal;
  1666.  *      -(x=anything) ** (k=integer) is (-1)**k * (x ** k);
  1667.  *      -(anything except 0) ** (non-integer) is NaN with signal;
  1668.  *
  1669.  * Accuracy:
  1670.  *      pow(x, y) returns x**y nearly rounded. In particular, on a SUN, a VAX,
  1671.  *      and a Zilog Z8000,
  1672.  *                      pow(integer, integer)
  1673.  *      always returns the correct integer provided it is representable.
  1674.  *      In a test run with 100,000 random arguments with 0 < x, y < 20.0
  1675.  *      on a VAX, the maximum observed error was 1.79 ulps (units in the
  1676.  *      last place).
  1677.  *
  1678.  * Constants :
  1679.  * The hexadecimal values are the intended ones for the following constants.
  1680.  * The decimal values may be used, provided that the compiler will convert
  1681.  * from decimal to binary accurately enough to produce the hexadecimal values
  1682.  * shown.
  1683.  */
  1684.  
  1685. #if defined(vax) || defined(tahoe)        /* VAX D format */
  1686. #include <errno.h>
  1687. extern double infnan() ;
  1688. #ifdef vax
  1689. #define _0x(A,B)        0x/**/A/**/B
  1690. #else   /* vax */
  1691. #define _0x(A,B)        0x/**/B/**/A
  1692. #endif  /* vax */
  1693. /* static double */
  1694. /* ln2hi  =  6.9314718055829871446E-1    , Hex  2^  0   *  .B17217F7D00000 */
  1695. /* ln2lo  =  1.6465949582897081279E-12   , Hex  2^-39   *  .E7BCD5E4F1D9CC */
  1696. /* invln2 =  1.4426950408889634148E0     , Hex  2^  1   *  .B8AA3B295C17F1 */
  1697. /* sqrt2  =  1.4142135623730950622E0     ; Hex  2^  1   *  .B504F333F9DE65 */
  1698. static long     ln2hix[] = { _0x(7217,4031), _0x(0000,f7d0)} ;
  1699. static long     ln2lox[] = { _0x(bcd5,2ce7), _0x(d9cc,e4f1)} ;
  1700. static long    invln2x[] = { _0x(aa3b,40b8), _0x(17f1,295c)} ;
  1701. static long     sqrt2x[] = { _0x(04f3,40b5), _0x(de65,33f9)} ;
  1702. #define  ln2hi    (*(double*) ln2hix)
  1703. #define  ln2lo    (*(double*) ln2lox)
  1704. #define  invln2   (*(double*) invln2x)
  1705. #define  sqrt2    (*(double*) sqrt2x)
  1706. #else   /* defined(vax)||defined(tahoe) */
  1707. static double
  1708. ln2hi  =  6.9314718036912381649E-1    , /* Hex  2^ -1   *  1.62E42FEE00000 */
  1709. ln2lo  =  1.9082149292705877000E-10   , /* Hex  2^-33   *  1.A39EF35793C76 */
  1710. invln2 =  1.4426950408889633870E0     , /* Hex  2^  0   *  1.71547652B82FE */
  1711. sqrt2  =  1.4142135623730951455E0     ; /* Hex  2^  0   *  1.6A09E667F3BCD */
  1712. #endif  /* defined(vax) || defined(tahoe) */
  1713.  
  1714. static double zero = 0.0 ;
  1715.  
  1716. double
  1717. pow(x, y)
  1718. double x, y ;
  1719. {
  1720.   double drem(), pow_p(), copysign(), t ;
  1721.   int finite() ;
  1722.  
  1723.        if (y == 0.0) return(1.0) ;
  1724. #if !defined(vax) && !defined(tahoe)
  1725.   else if (y == 1.0 || x != x) return(x) ;   /* if x is NaN or y = 1 */
  1726. #else
  1727.   else if (y == 1.0) return(x) ;             /* if y = 1 */
  1728. #endif  /* !defined(vax) && !defined(tahoe) */
  1729.  
  1730. #if !defined(vax) && !defined(tahoe)
  1731.   else if (y != y) return(y) ;               /* if y is NaN */
  1732. #endif  /* !defined(vax) && !defined(tahoe) */
  1733.   else if (!finite(y))                       /* if y is INF */
  1734.          if ((t = copysign(x, 1.0)) == 1.0)
  1735.            return(0.0 / zero) ;
  1736.     else if (t > 1.0) return((y > 0.0) ? y : 0.0) ;
  1737.     else return((y < 0.0) ? -y : 0.0) ;
  1738.   else if (y == 2.0) return(x * x) ;
  1739.   else if (y == -1.0) return(1.0 / x) ;
  1740.  
  1741. /* sign(x) = 1 */
  1742.  
  1743.   else if (copysign(1.0, x) == 1.0) return(pow_p(x, y)) ;
  1744.  
  1745. /* sign(x)= -1 */
  1746. /* if y is an even integer */
  1747.  
  1748.   else if ((t = drem(y, 2.0)) == 0.0) return(pow_p(-x, y)) ;
  1749.  
  1750. /* if y is an odd integer */
  1751.  
  1752.   else if (copysign(t, 1.0) == 1.0) return(-pow_p(-x, y)) ;
  1753.  
  1754. /* Henceforth y is not an integer */
  1755.  
  1756.   else if (x == 0.0) return((y > 0.0) ? -x : 1.0 / (-x)) ;   /* x is -0 */
  1757.   else                                  /* return NaN */
  1758.     {
  1759. #if defined(vax) || defined(tahoe)
  1760.       return(infnan(EDOM)) ;            /* NaN */
  1761. #else   /* defined(vax) || defined(tahoe) */
  1762.       return(0.0 / zero) ;
  1763. #endif  /* defined(vax) || defined(tahoe) */
  1764.      }
  1765. }
  1766.  
  1767.  
  1768. /* pow_p(x,y) return x**y for x with sign = 1 and finite y */
  1769.  
  1770. static double
  1771. pow_p(x, y)
  1772. double x, y ;
  1773. {
  1774.   double logb(), scalb(), copysign(), log__L(), exp__E() ;
  1775.   double c, s, t, z, tx, ty ;
  1776.  
  1777. #ifdef tahoe
  1778.   double tahoe_tmp ;
  1779. #endif  /* tahoe */
  1780.   float sx, sy ;
  1781.   long k = 0 ;
  1782.   int n, m ;
  1783.  
  1784.   if (x == 0.0 || !finite(x))             /* if x is +INF or +0 */
  1785.     {
  1786.  
  1787. #if defined(vax) || defined(tahoe)
  1788.       return((y > 0.0) ? x : infnan(ERANGE)) ;  /* if y < 0.0, return +INF */
  1789. #else   /* defined(vax) || defined(tahoe) */
  1790.       return((y > 0.0) ? x : 1.0 / x) ;
  1791. #endif  /* defined(vax) || defined(tahoe) */
  1792.      }
  1793.   if (x == 1.0) return(x) ;     /* if x = 1.0, return 1 since y is finite */
  1794.  
  1795. /* reduce x to z in [sqrt(1/2)-1, sqrt(2)-1] */
  1796.  
  1797.     z = scalb(x, -(n = logb(x))) ;
  1798.  
  1799. #if !defined(vax) && !defined(tahoe)      /* IEEE double; subnormal number */
  1800.   if (n <= -1022)
  1801.     {
  1802.       n += (m = logb(z)) ;
  1803.       z = scalb(z, -m) ;
  1804.     }
  1805. #endif  /* !defined(vax) && !defined(tahoe) */
  1806.  
  1807.   if (z >= sqrt2)
  1808.     {
  1809.       n += 1 ;
  1810.       z *= 0.5 ;
  1811.     }
  1812.   z -= 1.0 ;
  1813.  
  1814. /* log(x) = nlog2 + log(1 + z) ~ nlog2 + t + tx */
  1815.  
  1816.   s = z / (2.0 + z) ;
  1817.   c = z * z * 0.5 ;
  1818.   tx = s * (c + log__L(s * s)) ;
  1819.   t = z - (c - tx) ;
  1820.   tx += (z - t) - c ;
  1821.  
  1822. /* if y * log(x) is neither too big nor too small */
  1823.  
  1824.   if ((s = logb(y) + logb(n + t)) < 12.0)
  1825.     if (s > -60.0)
  1826.       {
  1827.  
  1828. /* compute y * log(x) ~ mlog2 + t + c */
  1829.  
  1830.         s = y * (n + invln2 * t) ;
  1831.         m = s + copysign(0.5, s) ;      /* m := nint(y * log(x)) */
  1832.         k = y ;
  1833.         if ((double) k == y)            /* if y is an integer */
  1834.           {
  1835.             k = m - k * n ;
  1836.             sx = t ;
  1837.             tx += (t - sx) ;
  1838.           }
  1839.         else                            /* if y is not an integer */
  1840.           {
  1841.             k = m ;
  1842.             tx += n * ln2lo ;
  1843.             sx = (c = n * ln2hi) + t ;
  1844.             tx += (c - sx) + t ;
  1845.           }
  1846.  
  1847. /* end of checking whether k == y */
  1848.  
  1849.         sy = y ;
  1850.         ty = y - sy ;                   /* y ~ sy + ty */
  1851.  
  1852. #ifdef tahoe
  1853.         s = (tahoe_tmp = sx) * sy - k * ln2hi ;
  1854. #else   /* tahoe */
  1855.         s = (double) sx * sy - k * ln2hi ;  /* (sy + ty) * (sx + tx) - kln2 */
  1856. #endif  /* tahoe */
  1857.  
  1858.         z = (tx * ty - k * ln2lo) ;
  1859.         tx = tx * sy ; ty = sx * ty ;
  1860.         t = ty + z ; t += tx ; t += s ;
  1861.         c = -((((t-s)-tx)-ty)-z) ;
  1862.  
  1863. /* return exp(y * log(x)) */
  1864.  
  1865.         t += exp__E(t,c) ;
  1866.         return(scalb(1.0 + t, m)) ;
  1867.       }
  1868.  
  1869. /* end of if log(y * log(x)) > -60.0 */
  1870.  
  1871.   else                  /* exp(+- tiny) = 1 with inexact flag */
  1872.     {
  1873.       ln2hi + ln2lo ;
  1874.       return(1.0) ;
  1875.     }
  1876.   else if (copysign(1.0, y) * (n + invln2 * t) < 0.0)
  1877.     return(scalb(1.0, -5000)) ;     /* exp(-(big#)) underflows to zero */
  1878.   else
  1879.     return(scalb(1.0, 5000)) ;      /* exp(+(big#)) overflows to INF */
  1880. }
  1881.  
  1882.  
  1883. /* Some IEEE standard 754 recommended functions and remainder and sqrt for
  1884.  * supporting the C elementary functions.
  1885.  ******************************************************************************
  1886.  * WARNING:
  1887.  *      These codes are developed (in double) to support the C elementary
  1888.  * functions temporarily. They are not universal, and some of them are very
  1889.  * slow (in particular, drem and sqrt is extremely inefficient). Each
  1890.  * computer system should have its implementation of these functions using
  1891.  * its own assembler.
  1892.  ******************************************************************************
  1893.  *
  1894.  * IEEE 754 required operations:
  1895.  *     drem(x, p)
  1896.  *              returns  x REM y  =  x - [x/y]*y , where [x/y] is the integer
  1897.  *              nearest x/y; in half way case, choose the even one.
  1898.  *     sqrt(x)
  1899.  *              returns the square root of x correctly rounded according to
  1900.  *              the rounding mod.
  1901.  *
  1902.  * IEEE 754 recommended functions:
  1903.  * (a) copysign(x, y)
  1904.  *              returns x with the sign of y.
  1905.  * (b) scalb(x, N)
  1906.  *              returns  x * (2 ** N), for integer values N.
  1907.  * (c) logb(x)
  1908.  *              returns the unbiased exponent of x, a signed integer in
  1909.  *              double precision, except that logb(0) is -INF, logb(INF)
  1910.  *              is +INF, and logb(NAN) is that NAN.
  1911.  * (d) finite(x)
  1912.  *              returns the value TRUE if -INF < x < +INF and returns
  1913.  *              FALSE otherwise.
  1914.  *
  1915.  * CODED IN C BY K.C. NG, 11/25/84;
  1916.  * REVISED BY K.C. NG on 1/22/85, 2/13/85, 3/24/85.
  1917.  */
  1918.  
  1919. #if      defined(vax) || defined(tahoe)      /* VAX D format */
  1920.   static unsigned short msign = 0x7fff, mexp = 0x7f80 ;
  1921.   static short  prep1 = 57, gap = 7, bias = 129 ;
  1922.   static double novf = 1.7E38, nunf = 3.0E-39 ;
  1923. #else /* defined(vax) || defined(tahoe) */
  1924.   static unsigned short msign = 0x7fff, mexp = 0x7ff0 ;
  1925.   static short prep1 = 54, gap = 4, bias = 1023 ;
  1926.   static double novf = 1.7E308, nunf = 3.0E-308 ;
  1927. #endif  /* defined(vax) || defined(tahoe) */
  1928.  
  1929. double
  1930. scalb(x, N)
  1931. double x ;
  1932. int N ;
  1933. {
  1934.   int k ;
  1935.   double scalb() ;
  1936.  
  1937. #ifdef national
  1938.   unsigned short *px = (unsigned short *) &x + 3 ;
  1939. #else   /* national */
  1940.   unsigned short *px = (unsigned short *) &x ;
  1941. #endif  /* national */
  1942.  
  1943.   if (x == 0.0) return(x) ;
  1944.  
  1945. #if defined(vax) || defined(tahoe)
  1946.  
  1947.   if ((k = *px & mexp) != ~msign)
  1948.     {
  1949.       if (N < -260) return(nunf * nunf) ;
  1950.       else if (N > 260)
  1951.         {
  1952.           extern double infnan(), copysign() ;
  1953.           return(copysign(infnan(ERANGE), x)) ;
  1954.         }
  1955. #else  /* defined(vax) || defined(tahoe) */
  1956.  
  1957.   if ((k = *px & mexp) != mexp)
  1958.     {
  1959.            if (N < -2100) return(nunf * nunf) ;
  1960.       else if (N > 2100) return(novf + novf) ;
  1961.       if (k == 0)
  1962.         {
  1963.           x *= scalb(1.0, (int) prep1) ;
  1964.           N -= prep1 ;
  1965.           return(scalb(x, N)) ;
  1966.         }
  1967. #endif  /* defined(vax) || defined(tahoe) */
  1968.  
  1969.       if ((k = (k >> gap) + N) > 0)
  1970.         if (k < (mexp >> gap)) *px = (*px & ~mexp) | (k << gap) ;
  1971.         else x = novf + novf ;               /* overflow */
  1972.       else
  1973.         if (k > -prep1)
  1974.           {                                  /* gradual underflow */
  1975.             *px = (*px & ~mexp) | (short) (1 << gap) ;
  1976.             x *= scalb(1.0, k-1) ;
  1977.           }
  1978.         else return(nunf * nunf) ;
  1979.     }
  1980.   return(x) ;
  1981. }
  1982.  
  1983.  
  1984. double
  1985. copysign(x, y)
  1986. double x, y ;
  1987. {
  1988. #ifdef   national
  1989.   unsigned short *px = (unsigned short *) &x + 3,
  1990.                  *py = (unsigned short *) &y + 3 ;
  1991. #else /* national */
  1992.   unsigned short *px = (unsigned short *) &x,
  1993.                  *py = (unsigned short *) &y ;
  1994. #endif  /* national */
  1995.  
  1996. #if defined(vax) || defined(tahoe)
  1997.   if ((*px & mexp) == 0) return(x) ;
  1998. #endif  /* defined(vax) || defined(tahoe) */
  1999.  
  2000.   *px = (*px & msign) | (*py & ~msign) ;
  2001.   return(x) ;
  2002. }
  2003.  
  2004.  
  2005. double
  2006. logb(x)
  2007. double x ;
  2008. {
  2009. #ifdef national
  2010.   short *px = (short *) &x + 3, k ;
  2011. #else   /* national */
  2012.   short *px = (short *) &x, k ;
  2013. #endif  /* national */
  2014.  
  2015. #if defined(vax) || defined(tahoe)
  2016.   return (int) (((*px & mexp) >> gap) - bias) ;
  2017. #else   /* defined(vax) || defined(tahoe) */
  2018.  
  2019.   if ((k = *px & mexp) != mexp)
  2020.          if (k != 0)   return((k >> gap) - bias) ;
  2021.     else if (x != 0.0) return(-1022.0) ;
  2022.     else               return(-(1.0 / zero)) ;
  2023.   else if (x != x) return(x) ;
  2024.   else
  2025.     {
  2026.       *px &= msign ;
  2027.       return(x) ;
  2028.     }
  2029. #endif  /* defined(vax) || defined(tahoe) */
  2030. }
  2031.  
  2032.  
  2033. finite(x)
  2034. double x ;
  2035. {
  2036. #if defined(vax) || defined(tahoe)
  2037.   return(1) ;
  2038. #else   /* defined(vax) || defined(tahoe) */
  2039. #ifdef national
  2040.   return((*((short *) &x + 3) & mexp) != mexp) ;
  2041. #else   /* national */
  2042.   return((*((short *) &x) & mexp) != mexp) ;
  2043. #endif  /* national */
  2044. #endif  /* defined(vax) || defined(tahoe) */
  2045. }
  2046.  
  2047.  
  2048. double
  2049. drem(x, p)
  2050. double x, p ;
  2051. {
  2052.   short sign ;
  2053.   double hp, dp, tmp, drem(), scalb() ;
  2054.   unsigned short k ;
  2055.  
  2056. #ifdef national
  2057.   unsigned short *px = (unsigned short *) &x   + 3,
  2058.                  *pp = (unsigned short *) &p   + 3,
  2059.                  *pd = (unsigned short *) &dp  + 3,
  2060.                  *pt = (unsigned short *) &tmp + 3 ;
  2061. #else   /* national */
  2062.   unsigned short *px = (unsigned short *) &x,
  2063.                  *pp = (unsigned short *) &p  ,
  2064.                  *pd = (unsigned short *) &dp ,
  2065.                  *pt = (unsigned short *) &tmp ;
  2066. #endif  /* national */
  2067.  
  2068.   *pp &= msign ;
  2069.  
  2070. #if defined(vax) || defined(tahoe)
  2071.   if ((*px & mexp) == ~msign)  /* is x a reserved operand? */
  2072. #else   /* defined(vax) || defined(tahoe) */
  2073.   if ((*px & mexp) == mexp)
  2074. #endif  /* defined(vax) || defined(tahoe) */
  2075.     return (x-p) - (x-p) ;     /* create nan if x is inf */
  2076.  
  2077.   if (p == 0.0)
  2078.     {
  2079.       doerr("drem", "SINGULARITY", EDOM) ;
  2080. #if defined(vax) || defined(tahoe)
  2081.       extern double infnan() ;
  2082.       return(infnan(EDOM)) ;
  2083. #else   /* defined(vax) || defined(tahoe) */
  2084.       return(0.0 / zero) ;
  2085. #endif  /* defined(vax) || defined(tahoe) */
  2086.     }
  2087.  
  2088. #if defined(vax) || defined(tahoe)
  2089.   if ((*pp & mexp) == ~msign)  /* is p a reserved operand? */
  2090. #else   /* defined(vax) || defined(tahoe) */
  2091.   if ((*pp & mexp) == mexp)
  2092. #endif  /* defined(vax)||defined(tahoe) */
  2093.     {
  2094.       if (p != p) return p ;
  2095.       else return x ;
  2096.     }
  2097.   else if (((*pp & mexp) >> gap) <= 1)
  2098.  
  2099. /* subnormal p, or almost subnormal p */
  2100.  
  2101.     {
  2102.       double b ;
  2103.       b = scalb(1.0, (int) prep1) ;
  2104.       p *= b ;
  2105.       x = drem(x, p) ;
  2106.       x *= b ;
  2107.       return(drem(x, p) / b) ;
  2108.     }
  2109.   else if (p >= novf / 2)
  2110.     {
  2111.       p /= 2 ;
  2112.       x /= 2 ;
  2113.       return(drem(x, p) * 2) ;
  2114.     }
  2115.   else
  2116.     {
  2117.       dp = p + p ;
  2118.       hp = p / 2 ;
  2119.       sign = *px & ~msign ;
  2120.       *px &= msign ;
  2121.       while (x > dp)
  2122.         {
  2123.           k = (*px & mexp) - (*pd & mexp) ;
  2124.           tmp = dp ;
  2125.           *pt += k ;
  2126.  
  2127. #if defined(vax) || defined(tahoe)
  2128.           if (x < tmp) *pt -= 128 ;
  2129. #else /* defined(vax) || defined(tahoe) */
  2130.           if (x < tmp) *pt -= 16 ;
  2131. #endif  /* defined(vax) || defined(tahoe) */
  2132.  
  2133.             x -= tmp ;
  2134.         }
  2135.       if (x > hp)
  2136.         {
  2137.           x -= p ;
  2138.           if (x >= hp) x -= p ;
  2139.         }
  2140.  
  2141. #if defined(vax) || defined(tahoe)
  2142.       if (x)
  2143. #endif  /* defined(vax) || defined(tahoe) */
  2144.         *px ^= sign ;
  2145.       return(x) ;
  2146.     }
  2147. }
  2148.  
  2149.  
  2150. /* exp__E(x,c)
  2151.  * ASSUMPTION: c << x  SO THAT  fl(x+c)=x.
  2152.  * (c is the correction term for x)
  2153.  * exp__E RETURNS
  2154.  *
  2155.  *                       /  exp(x+c) - 1 - x ,  1E-19 < |x| < .3465736
  2156.  *       exp__E(x,c) =  |
  2157.  *                       \  0 ,  |x| < 1E-19.
  2158.  *
  2159.  * DOUBLE PRECISION (IEEE 53 bits, VAX D FORMAT 56 BITS)
  2160.  * KERNEL FUNCTION OF EXP, EXPM1, POW FUNCTIONS
  2161.  * CODED IN C BY K.C. NG, 1/31/85;
  2162.  * REVISED BY K.C. NG on 3/16/85, 4/16/85.
  2163.  *
  2164.  * Required system supported function:
  2165.  *      copysign(x,y)
  2166.  *
  2167.  * Method:
  2168.  *      1. Rational approximation. Let r=x+c.
  2169.  *         Based on
  2170.  *                                   2 * sinh(r/2)
  2171.  *                exp(r) - 1 =   ----------------------   ,
  2172.  *                               cosh(r/2) - sinh(r/2)
  2173.  *         exp__E(r) is computed using
  2174.  *                   x*x            (x/2)*W - ( Q - ( 2*P  + x*P ) )
  2175.  *                   --- + (c + x*[---------------------------------- + c ])
  2176.  *                    2                          1 - W
  2177.  *         where  P := p1*x^2 + p2*x^4,
  2178.  *                Q := q1*x^2 + q2*x^4 (for 56 bits precision, add q3*x^6)
  2179.  *                W := x/2-(Q-x*P),
  2180.  *
  2181.  *         (See the listing below for the values of p1,p2,q1,q2,q3. The poly-
  2182.  *          nomials P and Q may be regarded as the approximations to sinh
  2183.  *          and cosh :
  2184.  *              sinh(r/2) =  r/2 + r * P  ,  cosh(r/2) =  1 + Q . )
  2185.  *
  2186.  *         The coefficients were obtained by a special Remez algorithm.
  2187.  *
  2188.  * Approximation error:
  2189.  *
  2190.  *   |  exp(x) - 1                         |        2**(-57),  (IEEE double)
  2191.  *   | ------------  -  (exp__E(x,0)+x)/x  |  <=
  2192.  *   |       x                             |        2**(-69).  (VAX D)
  2193.  *
  2194.  * Constants:
  2195.  * The hexadecimal values are the intended ones for the following constants.
  2196.  * The decimal values may be used, provided that the compiler will convert
  2197.  * from decimal to binary accurately enough to produce the hexadecimal values
  2198.  * shown.
  2199.  */
  2200.  
  2201. #if defined(vax) || defined(tahoe)        /* VAX D format */
  2202. #ifdef vax
  2203. #define _0x(A,B)        0x/**/A/**/B
  2204. #else   /* vax */
  2205. #define _0x(A,B)        0x/**/B/**/A
  2206. #endif  /* vax */
  2207.  
  2208. /* static double */
  2209. /* p1     =  1.5150724356786683059E-2    , Hex  2^ -6   *  .F83ABE67E1066A */
  2210. /* p2     =  6.3112487873718332688E-5    , Hex  2^-13   *  .845B4248CD0173 */
  2211. /* q1     =  1.1363478204690669916E-1    , Hex  2^ -3   *  .E8B95A44A2EC45 */
  2212. /* q2     =  1.2624568129896839182E-3    , Hex  2^ -9   *  .A5790572E4F5E7 */
  2213. /* q3     =  1.5021856115869022674E-6    ; Hex  2^-19   *  .C99EB4604AC395 */
  2214.  
  2215. static long        p1x[] = { _0x(3abe,3d78), _0x(066a,67e1) } ;
  2216. static long        p2x[] = { _0x(5b42,3984), _0x(0173,48cd) } ;
  2217. static long        q1x[] = { _0x(b95a,3ee8), _0x(ec45,44a2) } ;
  2218. static long        q2x[] = { _0x(7905,3ba5), _0x(f5e7,72e4) } ;
  2219. static long        q3x[] = { _0x(9eb4,36c9), _0x(c395,604a) } ;
  2220. #define  p1  (*(double*) p1x)
  2221. #define  p2  (*(double*) p2x)
  2222. #define  q1  (*(double*) q1x)
  2223. #define  q2  (*(double*) q2x)
  2224. #define  q3  (*(double*) q3x)
  2225. #else   /* defined(vax) || defined(tahoe) */
  2226.  
  2227. static double
  2228. p1 = 1.3887401997267371720E-2,     /* Hex  2^ -7   *  1.C70FF8B3CC2CF */
  2229. p2 = 3.3044019718331897649E-5,     /* Hex  2^-15   *  1.15317DF4526C4 */
  2230. q1 = 1.1110813732786649355E-1,     /* Hex  2^ -4   *  1.C719538248597 */
  2231. q2 = 9.9176615021572857300E-4 ;    /* Hex  2^-10   *  1.03FC4CB8C98E8 */
  2232. #endif  /* defined(vax) || defined(tahoe) */
  2233.  
  2234. double
  2235. exp__E(x, c)
  2236. double x, c ;
  2237. {
  2238.   static double small = 1.0E-19 ;
  2239.   double copysign(), z, p, q, xp, xh, w ;
  2240.  
  2241.   if (copysign(x, 1.0) > small)
  2242.      {
  2243.        z = x * x ;
  2244.        p = z * (p1 + z * p2) ;
  2245.  
  2246. #if defined(vax) || defined(tahoe)
  2247.        q = z * (q1 + z * (q2 + z * q3)) ;
  2248. #else   /* defined(vax) || defined(tahoe) */
  2249.        q = z * (q1 + z * q2) ;
  2250. #endif  /* defined(vax) || defined(tahoe) */
  2251.        xp = x * p ;
  2252.        xh = x * 0.5 ;
  2253.        w = xh - (q - xp) ;
  2254.        p = p + p ;
  2255.        c += x * ((xh * w - (q - (p + xp))) / (1.0 - w) + c) ;
  2256.        return(z * 0.5 + c) ;
  2257.      }
  2258.  
  2259. /* end of |x| > small */
  2260.  
  2261.    else
  2262.      {
  2263.        if (x != 0.0) 1.0 + small ;      /* raise the inexact flag */
  2264.        return(copysign(0.0, x)) ;
  2265.      }
  2266. }
  2267.  
  2268.  
  2269. /* log__L(Z)
  2270.  *              LOG(1+X) - 2S                          X
  2271.  * RETURN      ---------------  WHERE Z = S*S,  S = ------- , 0 <= Z <= .0294... *                    S                              2 + X
  2272.  *
  2273.  * DOUBLE PRECISION (VAX D FORMAT 56 bits or IEEE DOUBLE 53 BITS)
  2274.  * KERNEL FUNCTION FOR LOG; TO BE USED IN LOG1P, LOG, AND POW FUNCTIONS
  2275.  * CODED IN C BY K.C. NG, 1/19/85;
  2276.  * REVISED BY K.C. Ng, 2/3/85, 4/16/85.
  2277.  *
  2278.  * Method :
  2279.  *      1. Polynomial approximation: let s = x/(2+x).
  2280.  *         Based on log(1+x) = log(1+s) - log(1-s)
  2281.  *               = 2s + 2/3 s**3 + 2/5 s**5 + .....,
  2282.  *
  2283.  *         (log(1+x) - 2s)/s is computed by
  2284.  *
  2285.  *             z*(L1 + z*(L2 + z*(... (L7 + z*L8)...)))
  2286.  *
  2287.  *         where z=s*s. (See the listing below for Lk's values.) The
  2288.  *         coefficients are obtained by a special Remez algorithm.
  2289.  *
  2290.  * Accuracy:
  2291.  *      Assuming no rounding error, the maximum magnitude of the approximation
  2292.  *      error (absolute) is 2**(-58.49) for IEEE double, and 2**(-63.63)
  2293.  *      for VAX D format.
  2294.  *
  2295.  * Constants:
  2296.  * The hexadecimal values are the intended ones for the following constants.
  2297.  * The decimal values may be used, provided that the compiler will convert
  2298.  * from decimal to binary accurately enough to produce the hexadecimal values
  2299.  * shown.
  2300.  */
  2301.  
  2302. #if defined(vax) || defined(tahoe)        /* VAX D format (56 bits) */
  2303. #ifdef vax
  2304. #define _0x(A,B)        0x/**/A/**/B
  2305. #else   /* vax */
  2306. #define _0x(A,B)        0x/**/B/**/A
  2307. #endif  /* vax */
  2308.  
  2309. /* static double */
  2310. /* L1     =  6.6666666666666703212E-1    , Hex  2^  0   *  .AAAAAAAAAAAAC5 */
  2311. /* L2     =  3.9999999999970461961E-1    , Hex  2^ -1   *  .CCCCCCCCCC2684 */
  2312. /* L3     =  2.8571428579395698188E-1    , Hex  2^ -1   *  .92492492F85782 */
  2313. /* L4     =  2.2222221233634724402E-1    , Hex  2^ -2   *  .E38E3839B7AF2C */
  2314. /* L5     =  1.8181879517064680057E-1    , Hex  2^ -2   *  .BA2EB4CC39655E */
  2315. /* L6     =  1.5382888777946145467E-1    , Hex  2^ -2   *  .9D8551E8C5781D */
  2316. /* L7     =  1.3338356561139403517E-1    , Hex  2^ -2   *  .8895B3907FCD92 */
  2317. /* L8     =  1.2500000000000000000E-1    , Hex  2^ -2   *  .80000000000000 */
  2318.  
  2319. static long L1x[] = { _0x(aaaa,402a), _0x(aac5,aaaa) } ;
  2320. static long L2x[] = { _0x(cccc,3fcc), _0x(2684,cccc) } ;
  2321. static long L3x[] = { _0x(4924,3f92), _0x(5782,92f8) } ;
  2322. static long L4x[] = { _0x(8e38,3f63), _0x(af2c,39b7) } ;
  2323. static long L5x[] = { _0x(2eb4,3f3a), _0x(655e,cc39) } ;
  2324. static long L6x[] = { _0x(8551,3f1d), _0x(781d,e8c5) } ;
  2325. static long L7x[] = { _0x(95b3,3f08), _0x(cd92,907f) } ;
  2326. static long L8x[] = { _0x(0000,3f00), _0x(0000,0000) } ;
  2327.  
  2328. #define  L1  (*(double*) L1x)
  2329. #define  L2  (*(double*) L2x)
  2330. #define  L3  (*(double*) L3x)
  2331. #define  L4  (*(double*) L4x)
  2332. #define  L5  (*(double*) L5x)
  2333. #define  L6  (*(double*) L6x)
  2334. #define  L7  (*(double*) L7x)
  2335. #define  L8  (*(double*) L8x)
  2336. #else   /* defined(vax) || defined(tahoe) */
  2337.  
  2338. static double
  2339. L1 =  6.6666666666667340202E-1,       /* Hex  2^ -1   *  1.5555555555592 */
  2340. L2 =  3.9999999999416702146E-1,       /* Hex  2^ -2   *  1.999999997FF24 */
  2341. L3 =  2.8571428742008753154E-1,       /* Hex  2^ -2   *  1.24924941E07B4 */
  2342. L4 =  2.2222198607186277597E-1,       /* Hex  2^ -3   *  1.C71C52150BEA6 */
  2343. L5 =  1.8183562745289935658E-1,       /* Hex  2^ -3   *  1.74663CC94342F */
  2344. L6 =  1.5314087275331442206E-1,       /* Hex  2^ -3   *  1.39A1EC014045B */
  2345. L7 =  1.4795612545334174692E-1 ;      /* Hex  2^ -3   *  1.2F039F0085122 */
  2346. #endif  /* defined(vax) || defined(tahoe) */
  2347.  
  2348. double
  2349. log__L(z)
  2350. double z ;
  2351. {
  2352. #if defined(vax) || defined(tahoe)
  2353.   return(z * (L1 + z * (L2 + z * (L3 + z * (L4 + z *
  2354.              (L5 + z * (L6 + z * (L7 + z * L8)))))))) ;
  2355. #else   /* defined(vax) || defined(tahoe) */
  2356.   return(z * (L1 + z * (L2 + z * (L3 + z * (L4 + z *
  2357.              (L5 + z * (L6 + z * L7))))))) ;
  2358. #endif  /* defined(vax) || defined(tahoe) */
  2359. }
  2360. #endif /*NEED_POW*/
  2361.  
  2362.  
  2363. /*  Error detecting addition, subtraction, multiplication and division routines.
  2364.  *
  2365.  *  Routines supplied by Sisira Jayasinghe, Structural Dynamics Research Corp.
  2366.  *  2000 Eastman Dr. Milford, OH 45150 USA <spsisira@sdrc.UUCP>
  2367.  */
  2368.  
  2369. double
  2370. addition(x, y)
  2371. double x, y ;
  2372. {
  2373.   if (y > (HUGE - x)) doerr("add", "OVERFLOW", ERANGE) ;
  2374.   else
  2375.     {
  2376.       x += y ;
  2377.       return(x) ;
  2378.     }
  2379.   return(0.0) ;
  2380. }
  2381.  
  2382.  
  2383. double
  2384. subtraction(x, y)
  2385. double x, y ;
  2386. {
  2387.   if (y > (HUGE - x)) doerr("sub", "OVERFLOW", ERANGE) ;
  2388.   else
  2389.     {
  2390.       x -= y ;
  2391.       return(x) ;
  2392.     }
  2393.   return(0.0) ;
  2394. }
  2395.  
  2396.  
  2397. double
  2398. multiply(x, y)
  2399. double x, y ;
  2400. {
  2401.   double a, b ;
  2402.  
  2403.   if (x == 0.0 || y == 0.0) return(0.0) ;
  2404.   else
  2405.     {
  2406.       a = log(abs(x)) ;
  2407.       b = log(abs(y)) ;
  2408.       if ((a + b) >= log(HUGE)) doerr("mult", "OVERFLOW", ERANGE) ;
  2409.       else
  2410.         {
  2411.           x *= y ;
  2412.           return(x) ;
  2413.         }
  2414.     }
  2415.   return(0.0) ;
  2416. }
  2417.  
  2418.  
  2419. double
  2420. division(x, y)
  2421. double x, y ;
  2422. {
  2423.   double a, b ;
  2424.  
  2425.   if (x == 0.0) return(0.0) ;
  2426.   if (y == 0.0) doerr("div", "OVERFLOW", ERANGE) ;
  2427.   else
  2428.     {
  2429.       a = log(abs(x)) ;
  2430.       b = log(abs(y)) ;
  2431.       if ((a - b) >= log(HUGE)) doerr("div", "OVERFLOW", ERANGE) ;
  2432.       else
  2433.         {
  2434.           x /= y ;
  2435.           return(x) ;
  2436.         }
  2437.     }   
  2438.   return(0.0) ;
  2439. }
  2440.